package cn.lxh.system.aop;


import cn.lxh.system.domain.Logs;
import cn.lxh.system.mapper.LogsMapper;
import cn.lxh.util.IPAddressUtils;
import lombok.extern.slf4j.Slf4j;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.Signature;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.reflect.MethodSignature;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;

import javax.servlet.http.HttpServletRequest;
import java.net.URLDecoder;
import java.util.Arrays;

// around: 环绕通知
// LogsConfig面向切面编程类, Aop日志
@Component // 该类交给spring管控
@Aspect // 定义切面, 作用在Aop增强类上
@Slf4j
public class LogsConfig {

    @Autowired
    private HttpServletRequest httpServletRequest; // 需要导入web包

    @Autowired
    private LogsMapper logsMapper;

    @Around("execution(* cn.lxh.blog.service.*.*(..))")
    public Object around(ProceedingJoinPoint point) {
        try {
            // 开始时间
            long begin = System.currentTimeMillis();
            // 创建Logs对象
            Logs logs = new Logs();
            // 获取操作用户的id和姓名
            String userId = httpServletRequest.getHeader("userId");
            String username = httpServletRequest.getHeader("username");

        /*    // 解析token
            Payload payload = JwtUtil.parseJwtToken(httpServletRequest.getHeader("token"));
            // 获取登录信息
            Logininfo logininfo = payload.getLogininfo();
            // 获取用户id和用户名
            Long id = logininfo.getId();
            String username = logininfo.getUsername();*/

            if(userId != null && username != null) { // 防止空指针
                // username解码
                username = URLDecoder.decode(username, "UTF-8");
                // 给logs的属性赋值
                logs.setUserId(Long.valueOf(userId));
                logs.setUserName(username);
            }
            // 获取目标方法所在类的完全限定名
            String fullyQualifiedName = point.getTarget().getClass().getName();
            // 给logs的属性赋值
            logs.setClassName(fullyQualifiedName);
            // 获取签名对象
            Signature signature = point.getSignature();
            // 如果签名对象是方法签名类型或是它的实例
            if (signature instanceof MethodSignature) {
                // 强转
                MethodSignature methodSignature = (MethodSignature) signature;
                // 获取目标方法的返回值类型
                Class returnType = methodSignature.getReturnType();
                // 给logs的属性赋值
                logs.setReturnValue(returnType.getName());
            }
            // 获取目标方法名
            String methodName = signature.getName();
            // 给logs的属性赋值
            logs.setMethodName(methodName);
            // 执行目标方法
            Object result = point.proceed();
            // 获取传入目标方法的参数, 返回一个数组 (要在执行目标方法之后获取, 否则可能会获取的参数为null)
            Object[] args = point.getArgs();
            // 给logs的属性赋值
            logs.setMethodParams(Arrays.toString(args));
            // 获取ip地址
            String ipAddress = IPAddressUtils.getIpAdrress(httpServletRequest);
            // 给logs的属性赋值
            logs.setIp(ipAddress);
            // 结束时间
            long end = System.currentTimeMillis();
            // 给logs的属性赋值
            logs.setCostTime(end - begin);
            // 添加日志记录
            logsMapper.add(logs);
            // 返回结果值
            return result;
        } catch (Throwable e) {
            e.printStackTrace(); // 自己看的
            return null;
        }
    }

}